﻿/*
 * thpool.cpp
 *
 *  Created on: 2013-11-1
 *      Author: admin
 */

#include "thpool.h"
#include <iostream>
#include <atomic>
#include "TinyLog.h"

namespace n
{

static std::atomic<bool> g_stop(false);

//线程池中运行的函数
void thpool::th_founction(thpool* pool)
{
	//TDEBUG("thread "<< std::this_thread::get_id() << " start...");
	while (!g_stop){
		//从pool中取得一个任务
		std::function<void(void)> task;
		//TDEBUG("thread " << std::this_thread::get_id() << " geting task...");
		if (pool->pupup_task(task)){
			//TDEBUG("thread " << std::this_thread::get_id() << " getted one task,execute it");
			//执行此任务
			task();
		}else{
			//TDEBUG("thread " << std::this_thread::get_id() << " none task getted");
		}
	}

	//TDEBUG("thread "<< std::this_thread::get_id() << " exit");
}

thpool::thpool():
	m_cur_task_id(0)
{
}

thpool::~thpool()
{
	TDEBUG("main thread broadcast signal wen destroy ; stop is " << (g_stop ? "true" : "false"));
	m_cv.notify_all();
	for(auto& th:m_threads){
		th.join();
	}
}

void thpool::init(size_t n) throw()
{
	//start n threads 
    for(int i=0;i<n;i++){
		std::thread th(th_founction, this);
		m_threads.push_back(std::move<std::thread&>(th));
    }
}

size_t thpool::push_task(const std::function<void(void)>& task)
{
	size_t ret = m_cur_task_id++;
    //加入一条任务,是不是任务也应该用m_cv_mutex来保护?
    std::lock_guard<std::mutex> lk(m_cv_mutex);
	m_tasks[m_cur_task_id++] = task;
	TDEBUG("main thread broadcast signal ");
    m_cv.notify_all();
	return ret;
}

//this founction is called by thread
bool thpool::pupup_task(std::function<void(void)>& task_out)
{
	//从队列中获取一条任务，如果没有，就等待信号
	{
		//TDEBUG("thread "<< std::this_thread::get_id() << " check task");
		std::lock_guard<std::mutex> lk(m_cv_mutex);
		if (!m_tasks.empty()){
			TDEBUG("thread "<< std::this_thread::get_id() << " get one task");
			task_out = std::move(m_tasks.rbegin()->second);
			m_tasks.erase(m_tasks.rbegin()->first);
			return true;
		}
		//TDEBUG("thread "<< std::this_thread::get_id() << " no task");
	}

	//等待
	{
		std::unique_lock<std::mutex> lk(m_cv_mutex);
		//TDEBUG("thread "<< std::this_thread::get_id() << " wait for signal");
		m_cv.wait(lk,[&]{return (!m_tasks.empty() || g_stop);});
		//TDEBUG("thread "<< std::this_thread::get_id() << " recieved signal");
	}

	//返回false后，调用者应该再次调用本函数查看是否有任务
	return false;
}

void thpool::pause()
{

}

void thpool::resume()
{

}

} /* namespace n */
